package com.zhuangjie.shop.handler.activity;

import com.zhaungjie.base.conduit.TypeR;
import com.zhuangjie.mvc.helper.GeoHelper.GeoCoordinateUtils;
import com.zhuangjie.shop.dto.CartItemDTO;
import com.zhuangjie.shop.entity.Shop;
import com.zhuangjie.shop.enums.BusinessTypeEnum;
import com.zhuangjie.shop.feign.OrderFeignService;
import com.zhuangjie.shop.handler.activity.handler.ActivityEnvRequireMetaInformation;
import com.zhuangjie.shop.service.ShopService;
import lombok.Getter;
import lombok.Setter;
import org.springframework.context.ApplicationContext;

import java.math.BigDecimal;
import java.util.Objects;

/**
 * ActivityEnvRequireMetaInformation更上层的环境变量
 * 依赖ActivityEnvRequireMetaInformation来按需计算
 */
@Setter
public class ActivityEnv {
    /**
     * 需要一些服务XXService
     */
    private ShopService shopService;
    private OrderFeignService orderFeignService;
    /**
     * 构成需要的信息需要的元信息
     */
    @Getter
    private ActivityEnvRequireMetaInformation metaInformation;

    /**
     * 在构建时需要传入ApplicationContext需要用到一个service进行查询
     *
     * @param context
     */
    public ActivityEnv(ApplicationContext context, ActivityEnvRequireMetaInformation metaInformation) {
        // 正常的构造赋值
        this.metaInformation = metaInformation;
        // 利用context -> 本类属性XXService
        shopService = context.getBean(ShopService.class);
        orderFeignService = context.getBean(OrderFeignService.class);

    }

    /**
     * 店铺对象信息（避免多次查询）
     */
    private Shop shop;

    /**
     * 店铺与用户距离
     */
    private Double distance;
    /**
     * 是否会员
     */
    private Boolean isMember;
    /**
     * 是否新客
     */
    private Boolean isNewCustomer;

    /**
     * 菜品总价
     *
     * @return
     */
    private BigDecimal dishListSumPrice;

    public BigDecimal getDishListSumPrice() {
        // 双重检查创建shop
        if (dishListSumPrice == null) {
            synchronized (this) {
                if (dishListSumPrice == null) {
                    try {
                        this.dishListSumPrice = this.metaInformation.getDishList().stream()
                                .map(CartItemDTO::getPrice)
                                .reduce(BigDecimal.ZERO, BigDecimal::add);
                    } catch (Exception e) {
                        throw new RuntimeException("无法确认菜品总价(未使用活动与券的价格)！");
                    }
                }
            }
        }
        return this.dishListSumPrice;
    }


    public Double getDistance() {
        if (this.distance == null) {
            synchronized (this) {
                if (this.distance == null) {
                    // 如果不是配送单 或者 用户没有可用的地址 返回null
                    if (!Objects.equals(metaInformation.getReceivingMethod(), BusinessTypeEnum.DELIVERY.getValue()) || metaInformation.getUserGeoCoordinates() == null) {
                        return null;
                    }
                    Shop shopInfo = getShop();
                    // 计算距离
                    this.distance = GeoCoordinateUtils.calculateDistance(
                            shopInfo.getLongitude(), shopInfo.getLatitude(),
                            metaInformation.getUserGeoCoordinates().getLongitude(), metaInformation.getUserGeoCoordinates().getLatitude());

                }
            }
        }
        return this.distance;

   }

    public Boolean getMember() {
        // TODO 当前系统没有会员模式，直接返回true
        return true;
    }


    /**
     * 当多线程计算优惠时，需要同步创建shop
     *
     * @return
     */
    public Shop getShop() {
        // 双重检查创建shop
        if (shop == null) {
            synchronized (this) {
                if (shop == null) {
                    shop = shopService.getById(metaInformation.getShopId());
                }
            }
        }
        return shop;
    }

    public boolean getIsNewCustomer() {
        // 双重检查创建shop
        if (isNewCustomer == null) {
            synchronized (this) {
                if (isNewCustomer == null) {
                    try {
                        isNewCustomer = TypeR.extract(orderFeignService.isNewCustomer(metaInformation.getShopId()));
                    } catch (Exception e) {
                        throw new RuntimeException("无法确定是否用户是否为新客！");
                    }
                }
            }
        }
        return isNewCustomer;
    }
}
